﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Odds.Entity;
using HtmlAgilityPack;
using System.Text.RegularExpressions;
using JJY.CommonHelper;
using System.Reflection;
namespace Odds.Business
{
    public class MatchDataOrganizeMonitor
    {
        private const string tableTitleID = "artibodyTitle";
        private const string tableID = "artibody";
        private const string inputPublishDateID = "pub_date";
        private readonly string EmptyString = string.Empty;

        private OddsIssue oddsIssue = new OddsIssue();
        private OddsIssueHtml oddsIssueHtml = new OddsIssueHtml();
        private List<OddsTableRecorder> oddsTableRecorderSet = new List<OddsTableRecorder>();
        private List<OddsCompany> oddsCompanySet = new List<OddsCompany>();
        private List<OddsTeam> oddsTeamSet = new List<OddsTeam>();
        private List<OddsMatchType> oddsMatchTypeSet = new List<OddsMatchType>();


        public OddsIssue _OddsIssue
        {
            get { return oddsIssue; }
        }

        public OddsIssueHtml _OddsIssueHtml
        {
            get { return oddsIssueHtml; }
        }

        public List<OddsTableRecorder> _OddsTableRecoderSet
        {
            get { return oddsTableRecorderSet; }
        }

        public List<OddsCompany> _OddsCompanySet
        {
            get { return oddsCompanySet; }
        }

        public List<OddsTeam> _OddsTeamSet
        {
            get { return oddsTeamSet; }
        }

        public List<OddsMatchType> _OddsMatchTypeSet
        {
            get { return oddsMatchTypeSet; }
        }


        public MatchDataOrganizeMonitor(string strUrl)
        {
            int issueID = 0;
            DateTime publishDate = DateTime.Parse("1900-1-1");
            DateTime oddsDateTime = DateTime.Parse("1900-1-1");
            List<OddsCompany> tempOddsCompanySet = new List<OddsCompany>();

            string str = HttpRequestService.GetHtmlSourceByUrl(strUrl,Encoding.GetEncoding("gb2312"))
                .Replace(@"\t", EmptyString).Replace(@"\r", EmptyString).Replace(@"\n", EmptyString)
                .Replace("&nbsp;", EmptyString).Replace("　", EmptyString).Trim().ToUTF8();

            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(str);

            //get issue number from title
            HtmlNode nodeTitleSet = doc.DocumentNode.SelectNodes("//h1[@id='" + tableTitleID + "']")[0];
            int.TryParse(Regex.Matches(nodeTitleSet.InnerText, "\\d{5}")[0].ToString(), out issueID);

            //get publish date, this is also issue end date
            HtmlNode nodePublishDate = doc.DocumentNode.SelectNodes("//span[@id='" + inputPublishDateID + "']")[0];
            DateTime.TryParse(Regex.Matches(nodePublishDate.InnerText, "\\d{4}年\\d{1,2}月\\d{1,2}日".ToUTF8())[0].ToString()
                .Replace("年".ToUTF8(), "-").Replace("月".ToUTF8(), "-").Replace("日".ToUTF8(), EmptyString), out publishDate);

            oddsIssue.IssueRealID = issueID;
            oddsIssue.EndDate = publishDate;

            oddsIssueHtml.IssueRealID = issueID;
            oddsIssueHtml.IssueHtml = str;
            oddsIssueHtml.IssueUrl = strUrl;

            //get all the tr from the tabel which include data we need
            HtmlNodeCollection nodeTRSet = doc.DocumentNode.SelectNodes("//div[@id='" + tableID + "']/table/tbody/tr/td/table/tbody/tr");
            if (nodeTRSet == null)
            {
                nodeTRSet = doc.DocumentNode.SelectNodes("//div[@id='" + tableID + "']/table/tr/td/table/tr");
                if (nodeTRSet == null)
                {
                    nodeTRSet = doc.DocumentNode.SelectNodes("//div[@id='" + tableID + "']/div/table/tr/td/table/tr");
                    if (nodeTRSet == null)
                    {
                        nodeTRSet = doc.DocumentNode.SelectNodes("//div[@id='" + tableID + "']/div/table/tbody/tr/td/table/tbody/tr");
                    }
                }
            }

            string matchType = EmptyString;
            string homeTeam = EmptyString, visitingTeam = EmptyString;

            byte indexInIssueItem = 0;//using for ordering oddsitem, normally order by odds time, but order by int is better.
            byte indexInIssue = 0;//using for oddsitem, index of oddsitem in issue
            foreach (HtmlNode nodeTR in nodeTRSet)
            {
                //DateTime oddsDateTime = publishDate;

                HtmlNodeCollection nodeTDSet = doc.DocumentNode.SelectNodes(nodeTR.XPath + "/td");

                //it's odds' company name row
                if (nodeTDSet.Count == 5)
                {
                    tempOddsCompanySet.Clear();
                    tempOddsCompanySet.Add(new OddsCompany() { CompanyName = nodeTDSet[1].InnerText.Replace(" ", EmptyString).ToLower() });
                    tempOddsCompanySet.Add(new OddsCompany() { CompanyName = nodeTDSet[2].InnerText.Replace(" ", EmptyString).ToLower() });
                    tempOddsCompanySet.Add(new OddsCompany() { CompanyName = nodeTDSet[3].InnerText.Replace(" ", EmptyString).ToLower() });
                    tempOddsCompanySet.Add(new OddsCompany() { CompanyName = nodeTDSet[4].InnerText.Replace(" ", EmptyString).ToLower() });

                    foreach (OddsCompany company in tempOddsCompanySet)
                    {
                        //LiBo mutil-name check
                        if (company.CompanyName.IndexOf("立博".ToUTF8()) > -1)
                        {
                            company.CompanyName = "立博".ToUTF8();
                        }

                        if (!oddsCompanySet.Any(o => o.CompanyName.ToLower() == company.CompanyName.ToLower()))
                        {
                            oddsCompanySet.Add(company);
                        }
                    }
                }

                //it's row include match type
                else if (nodeTDSet.Count == 13)
                {
                    matchType = nodeTDSet[0].InnerText.Replace(" ", EmptyString);
                    oddsMatchTypeSet.Add(new OddsMatchType()
                    {
                        MatchTypeName = matchType
                    });
                }
                //it's row include lottery data
                else if (nodeTDSet.Count == 14)
                {
                    indexInIssueItem++;

                    //the row has IssueItemIndex, which is the odds begin row
                    if (!string.IsNullOrEmpty(nodeTDSet[0].InnerText.Trim()) && byte.TryParse(nodeTDSet[0].InnerText.Trim(), out indexInIssue))
                    {
                        //set as init time
                        oddsDateTime = DateTime.Parse("1900-1-1");

                        //set this variable = 1 when the first column have number
                        indexInIssueItem = 1;

                        //get home team's name and visiting team's name
                        OddsTeam oddsHomeTeam = new OddsTeam();
                        oddsHomeTeam.TeamName = nodeTDSet[1].InnerText.Split(new string[] { "VS" }, StringSplitOptions.RemoveEmptyEntries)[0]
                            .Replace(" ", EmptyString).Replace("(中立场地)".ToUTF8(), EmptyString).Replace("(延期)".ToUTF8(), EmptyString);
                        homeTeam = oddsHomeTeam.TeamName;
                        if (!oddsTeamSet.Any(o => o.TeamName == oddsHomeTeam.TeamName))
                        {
                            oddsTeamSet.Add(oddsHomeTeam);
                        }

                        OddsTeam oddsVisitTeam = new OddsTeam();
                        oddsVisitTeam.TeamName = nodeTDSet[1].InnerText.Split(new string[] { "VS" }, StringSplitOptions.RemoveEmptyEntries)[1]
                            .Replace(" ", EmptyString).Replace("(中立场地)".ToUTF8(), EmptyString).Replace("(延期)".ToUTF8(), EmptyString);
                        visitingTeam = oddsVisitTeam.TeamName;
                        if (!oddsTeamSet.Any(o => o.TeamName == oddsVisitTeam.TeamName))
                        {
                            oddsTeamSet.Add(oddsVisitTeam);
                        }                        
                    }
                    else
                    {
                        //get odds time
                        if (nodeTDSet[1].InnerText.IndexOf("月".ToUTF8()) > -1)
                        {
                            //sometime publish date and odds date in different month
                            DateTime.TryParse(publishDate.Year.ToString() + "-" +
                                  nodeTDSet[1].InnerText.Replace("月".ToUTF8(), "-").Replace("日".ToUTF8(), " ").Replace("：".ToUTF8(), ":"), out oddsDateTime);
                        }
                        else
                        {
                            //some odds time is empty, keep it as 1900-1-1
                            if (nodeTDSet[1].InnerText.Trim() != EmptyString)
                            {                                
                                string date = publishDate.Year.ToString() + "-" + publishDate.Month.ToString() +
                                    "-" + nodeTDSet[1].InnerText.Replace("日".ToUTF8(), " ").Replace("：".ToUTF8(), ":");

                                //normally date
                                if (!DateTime.TryParse(date, out oddsDateTime))
                                {
                                    //if publish date is 1st.Feb odds date is Jan.31, will parse date like below
                                    date = publishDate.Year.ToString() + "-" + publishDate.AddMonths(-1).Month.ToString() +
                                    "-" + nodeTDSet[1].InnerText.Replace("日".ToUTF8(), " ").Replace("：".ToUTF8(), ":");
                                    DateTime.TryParse(date, out oddsDateTime);
                                }
                            }
                        }
                    }

                    if (indexInIssue > 0)
                    {
                        int indexTemp = 0;
                        foreach (OddsCompany oddsCompany in tempOddsCompanySet)
                        {
                            OddsTableRecorder oddsTableRecorder = new OddsTableRecorder()
                            {
                                IssueID = issueID,
                                OddsIndexInIssueItem = indexInIssueItem,
                                IssuePublishDate = publishDate,
                                IndexInIssue = indexInIssue,
                                MatchType = matchType,
                                OddsPublishDateTime = oddsDateTime,
                                HomeTeam = homeTeam,
                                VisitingTeam = visitingTeam,
                            };

                            oddsTableRecorder.OddsCompany = oddsCompany.CompanyName;

                            decimal oddsWin = 0, oddsDraw = 0, oddsLose = 0;
                            if (decimal.TryParse(nodeTDSet[3 * indexTemp + 2].InnerText, out oddsWin))
                            {
                                oddsTableRecorder.OddsWin = oddsWin;
                            }
                            if (decimal.TryParse(nodeTDSet[3 * indexTemp + 3].InnerText, out oddsDraw))
                            {
                                oddsTableRecorder.OddsDraw = oddsDraw;
                            }
                            if (decimal.TryParse(nodeTDSet[3 * indexTemp + 4].InnerText, out oddsLose))
                            {
                                oddsTableRecorder.OddsLose = oddsLose;
                            }

                            if ((oddsWin > 0 && oddsDraw > 0 && oddsLose > 0) || indexInIssueItem == 1)
                            {
                                oddsTableRecorderSet.Add(oddsTableRecorder);
                            }

                            oddsTableRecorderSet.Add(oddsTableRecorder);

                            indexTemp++;
                        }
                    }
                }
            }
        }

        public string ShowRecorderTable()
        {
            StringBuilder result = new StringBuilder();
            result.AppendFormat("<table>");
            foreach (OddsTableRecorder o in oddsTableRecorderSet)
            {
                Type t = typeof(OddsTableRecorder);
                result.AppendFormat("<tr>");
                foreach (PropertyInfo p in t.GetProperties())
                {
                    result.AppendFormat("<td>{0}</td>", p.GetValue(o, null));
                }
                result.AppendFormat("</tr>");
            }
            result.AppendFormat("</table>");
            return result.ToString();
        }        
    }
}
